#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import re
from datetime import datetime
from typing import Dict, List, Set, Optional, Tuple
from enum import Enum
import logging
from tree_sitter import Tree, Node
# 导入数据结构
from parser.refactor.data_structures import (
    ClassInfo, ParserContext, DependencyContext, DependencyType,
    MethodInfo, FieldInfo, AnnotationInfo, GraphNodeInfo, GraphEdgeInfo,
    MetadataInfo, RelationshipInfo, RelationshipCollection,
    ClassType, Visibility, FileInfo, ParameterInfo, CommentInfo
)
from parser.refactor.java_metadata_extractor.java_metadata_extractor import JavaMetadataExtractor
from parser.refactor.java_node_type import (JavaNodeType)

logger = logging.getLogger(__name__)


class JavaCommentExtractor(JavaMetadataExtractor):
    """Java注释元数据提取器"""

    def get_comment_info(self, node:Node, package_name: str, code_bytes: bytes = None) -> Optional[CommentInfo]:
        """
        获取当前节点的注释元信息

        Args:
            node: 当前节点
            package_name: 包名
            code_bytes: 源代码字节

        Returns:
            CommentInfo: 注释信息对象，如果解析失败则返回None
        """
        # 提取注释信息
        previous_node = node.prev_sibling
        if previous_node and JavaNodeType.is_comment(previous_node.type):
            java_comment_extractor = JavaCommentExtractor()
            # 获取注释修饰目标名
            target_full_name = java_comment_extractor.get_comment_next_node_full_name(previous_node, code_bytes, package_name)
            return java_comment_extractor.extract_comment_info(previous_node, code_bytes, target_full_name)

        return None


    def extract_comment_info(self, node: Node, code_bytes: bytes, target_name: str) -> Optional[CommentInfo]:
        """
        从注释节点提取注释信息

        Args:
            node: 注释节点
            code_bytes: 源代码字节
            target_name: 注释目标的全限定名

        Returns:
            CommentInfo: 注释信息对象，如果解析失败则返回None
        """
        try:
            # 获取注释文本
            comment_text = self.get_node_text(node, code_bytes)

            # 根据注释类型处理文本
            if node.type == JavaNodeType.LINE_COMMENT:  # 单行注释 //
                # 移除 // 前缀
                content = comment_text[2:].strip()
            elif node.type == JavaNodeType.BLOCK_COMMENT:  # 多行注释 /* */
                # 移除 /* 和 */ 并处理每行
                content = comment_text[2:-2].strip()
                # 处理多行注释的格式
                content = self._format_block_comment(content)
            else:
                logger.warning(f"未知的注释类型: {node.type}")
                return None

            return CommentInfo(
                target=target_name,
                content=content
            )

        except Exception as e:
            logger.error(f"提取注释信息时出错: {str(e)}")
            return None

    def _format_block_comment(self, comment: str) -> str:
        """
        格式化多行注释内容

        Args:
            comment: 原始注释内容

        Returns:
            str: 格式化后的注释内容
        """
        lines = comment.split('\n')
        formatted_lines = []

        for line in lines:
            # 移除行首的 * 和空白
            cleaned_line = line.strip()
            if cleaned_line.startswith('*'):
                cleaned_line = cleaned_line[1:].strip()
            formatted_lines.append(cleaned_line)

        # 移除开头和结尾的空行
        while formatted_lines and not formatted_lines[0]:
            formatted_lines.pop(0)
        while formatted_lines and not formatted_lines[-1]:
            formatted_lines.pop()

        return '\n'.join(formatted_lines)

    def get_comment_next_node_full_name(self, comment_node: Node, code_bytes: bytes, package_name: str) -> str:
        """
        获取当前注释节点的下一个节点的全限定名, 即修饰的目标的全限定名

        Args:
            comment_node: 当前注释节点
            code_bytes: 源代码字节表示
            package_name: 包名

        Returns:
            str: 下一个节点的全限定名

        """
        # 获取注释的下一个兄弟节点
        next_sibling = comment_node.next_sibling

        if next_sibling:
            if next_sibling.type == 'class_declaration':
                # 类注释
                for child in next_sibling.children:
                    if child.type == JavaNodeType.IDENTIFIER:
                        class_name = self.get_node_text(child, code_bytes)
                        return f"{package_name}.{class_name}" if package_name else class_name

            elif next_sibling.type == JavaNodeType.METHOD_DECLARATION:
                # 方法注释
                method_name = None
                class_name = None

                # 获取方法名
                for child in next_sibling.children:
                    if child.type == JavaNodeType.IDENTIFIER:
                        method_name = self.get_node_text(child, code_bytes)
                        break

                # 获取所属类名
                current = next_sibling
                while current.parent:
                    current = current.parent
                    if current.type == JavaNodeType.CLASS_DECLARATION:
                        for child in current.children:
                            if child.type == JavaNodeType.IDENTIFIER:
                                class_name = self.get_node_text(child, code_bytes)
                                break
                        break

                if class_name and method_name:
                    parameters = self._extract_method_parameters(next_sibling, code_bytes)
                    return f"{package_name}.{class_name}#{method_name}.{parameters}"

        return package_name

    def _extract_method_parameters(self, node: Node, code_bytes: bytes) -> List[ParameterInfo]:
        """提取方法参数信息"""
        parameters = []

        # 查找形参列表节点
        formal_parameters = None
        for child in node.children:
            if child.type == JavaNodeType.FORMAL_PARAMETERS:
                formal_parameters = child
                break

        if formal_parameters:
            for child in formal_parameters.children:
                if child.type == JavaNodeType.FORMAL_PARAMETER:
                    # 获取参数名
                    name_node = next((c for c in child.children
                                      if c.type == JavaNodeType.IDENTIFIER), None)

                    # 获取参数类型
                    type_node = next((c for c in child.children
                                      if JavaNodeType.is_parameter_type(c.type)), None)

                    if type_node and name_node:
                        parameters.append(ParameterInfo(
                            name=self.get_node_text(name_node, code_bytes),
                            type=self.get_node_text(type_node, code_bytes)
                        ))

        return parameters
